package slxy.jiangtao.dts.controller.admin;

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.io.FileUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.jeecgframework.poi.excel.ExcelExportUtil;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import slxy.jiangtao.dts.controller.BaseController;
import slxy.jiangtao.dts.core.common.bean.Constants;
import slxy.jiangtao.dts.core.common.bean.FormQuery;
import slxy.jiangtao.dts.core.common.bean.JSONResult;
import slxy.jiangtao.dts.core.common.hibernate.qbc.Page;
import slxy.jiangtao.dts.core.util.*;
import slxy.jiangtao.dts.entity.business.Archives;
import slxy.jiangtao.dts.entity.business.Task;
import slxy.jiangtao.dts.entity.sys.SystemFiles;
import slxy.jiangtao.dts.service.sys.SystemFileService;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Code must be sexy
 * Created by Jiang Tao on 2017/3/30.
 */
@Controller
@RequestMapping("filesupload")
public class FilesUploadController extends BaseController {
    private static final Logger logger = LoggerFactory.getLogger(FilesUploadController.class);

    @Autowired
    SystemFileService systemFileService;

    /**
     * ueditor文件上传方法
     * 支持多文件上传支持
     *
     * @param upfile
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "ueditor")
    @ResponseBody
    public Map uploadFile(@RequestParam(value = "upfile", required = false) MultipartFile[] upfile) throws Exception {
        Map<String, String> map = new HashMap<>();
        if (upfile != null && upfile.length > 0) {
            for (int i = 0; i < upfile.length; i++) {
                MultipartFile file = upfile[i];
                String fileName = file.getOriginalFilename();
                //对文件类型（后缀名）判定
                int lastDotIndex = fileName.lastIndexOf(".");
                String fileExt = fileName.substring(lastDotIndex + 1, fileName.length());
                if (StringUtil.isEmpty(fileName) || StringUtil.isEmpty(fileExt) || Arrays.stream(Constants.ALLOW_EXTS).noneMatch(ext -> ext.equalsIgnoreCase(fileExt))) {
                    map.put("state", "上传失败!");
                    return map;
                }
                //构造保存文件名
                String newFilename = UUIDGenerator.generate() + "." + fileExt;
                String childrenPath = new SimpleDateFormat("yyyy/MM").format(new Date());
                try {
                    FileUtils.copyInputStreamToFile(file.getInputStream(), new File(Constants.UEDITOR_PATH + File.separator + childrenPath, newFilename));
                    map.put("url", childrenPath + "/" + newFilename);
                    map.put("name", newFilename);
                    map.put("state", "SUCCESS");
                    logger.info("图片上传成功：" + newFilename);
                } catch (Exception e) {
                    logger.error("上传图片失败: " + newFilename, e);
                    map.put("state", "上传失败!");
                }
            }
        }
        return map;
    }

    @RequestMapping(value = "uploadify/{localFileName}", method = RequestMethod.POST)
    @ResponseBody
    public JSONResult uploadFile(HttpServletRequest request, @PathVariable String localFileName) throws IOException {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        MultipartFile multipartFile = multipartRequest.getFile("file");
        long size = multipartFile.getSize();
        //获得文件原始名称
        String name = multipartFile.getOriginalFilename();
        //对文件类型（后缀名）判定
        int lastDotIndex = name.lastIndexOf(".");
        String fileExt = name.substring(lastDotIndex + 1, name.length());
        if (StringUtil.isEmpty(name) || StringUtil.isEmpty(fileExt) || Arrays.stream(Constants.ALLOW_EXTS).noneMatch(ext -> ext.equalsIgnoreCase(fileExt))) {
            return JSONResult.failure("错误的文件类型");
        }
        // 构建图片保存的虚拟目录
        String path = localFileName + File.separator + DateUtils.getDate("yyyy" + File.separator + "MM");
        // 构建图片保存的磁盘完整目录
        String localPath = Constants.UPLOADIFY_PATH + File.separator + path;
        //文件保存操作
        SystemFiles systemFiles = new SystemFiles();
        try {
            String fileNo = UUIDGenerator.generate();
            systemFiles.setNo(fileNo);
            systemFiles.setName(name);
            systemFiles.setSuffix(fileExt);
            systemFiles.setType(localFileName);
            systemFiles.setOperTime(DateUtils.getDate("yyyy-MM-dd HH:mm:ss"));
            systemFiles.setPath(path);
            systemFiles.setLocalPath(localPath);
            systemFiles.setSize(size);
            systemFiles.setOperName(getUserInSession(request).getName());
            commonService.save(systemFiles);
            FileUtils.copyInputStreamToFile(multipartFile.getInputStream(), new File(localPath, name));
            logger.info(name + "文件上传成功");
        } catch (Exception e) {
            logger.error(name + "保存文件失败: ", e);
            return JSONResult.failure("上传失败");
        }
        return JSONResult.success(systemFiles);
    }

    /**
     * word文档上传并同时生成html文件:主要用于档案管理模块
     */
    @RequestMapping(value = "uploadify/document/{localFileName}", method = RequestMethod.POST)
    @ResponseBody
    public JSONResult wordupload(@PathVariable String localFileName, HttpServletRequest request) {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        MultipartFile multipartFile = multipartRequest.getFile("file");
        long size = multipartFile.getSize();
        //获得文件原始名称
        String name = multipartFile.getOriginalFilename();
        //对文件类型（后缀名）判定
        int lastDotIndex = name.lastIndexOf(".");
        String fileExt = name.substring(lastDotIndex + 1, name.length());
        if (StringUtil.isEmpty(name) || StringUtil.isEmpty(fileExt) || Arrays.stream(Constants.Allow_EXTS_WORD).noneMatch(ext -> ext.equalsIgnoreCase(fileExt))) {
            return JSONResult.failure("错误的文件类型");
        }
        // 构建图片保存的虚拟目录
        String path = localFileName + "/" + DateUtils.getDate("yyyy");
        // 构建图片保存的磁盘完整目录
        String localPath = Constants.UPLOADIFY_PATH + File.separator + path;
        //文件保存操作
        SystemFiles systemFiles = new SystemFiles();
        String fileNo = UUIDGenerator.generate();
        //构造保存文件名
        String newFilename = fileNo + "." + fileExt;
        try {
            systemFiles.setNo(fileNo);
            systemFiles.setName(name);
            systemFiles.setSuffix(fileExt);
            systemFiles.setType(localFileName);
            systemFiles.setOperTime(DateUtils.getDate("yyyy-MM-dd HH:mm:ss"));
            systemFiles.setPath(path);
            systemFiles.setLocalPath(localPath);
            systemFiles.setSize(size);
            systemFiles.setOperName(getUserInSession(request).getName());
            commonService.save(systemFiles);
            FileUtils.copyInputStreamToFile(multipartFile.getInputStream(), new File(localPath, newFilename));
            logger.info(name + "文件上传成功");
        } catch (Exception e) {
            logger.error(name + "保存文件失败: ", e);
            return JSONResult.failure("上传失败");
        }

        //word向html转换
        try {
            JacobUtil.wordToHtml(localPath + File.separator + newFilename, localPath + File.separator + fileNo + ".html");
        } catch (Exception e) {
            return JSONResult.failure("文件转换出错");
        }

        //实体保存
        try {
            switch (localFileName) {
                case "Archives": {
                    Archives archives = new Archives();
                    archives.setName(name.substring(0, name.lastIndexOf(".")));
                    archives.setCreatTime(DateUtils.getDate("yyyy-MM-dd HH:mm:ss"));
                    archives.setCreator(getUserInSession(request).getName());
                    archives.setFileNo(fileNo);
                    commonService.save(archives);
                    break;
                }
                case "Summary":
                    break;
                case "Article":
                    break;
                default: {
                    logger.error("未定义的实体：" + localFileName);
                    return JSONResult.failure("无效的上传路径");
                }
            }
        } catch (Exception e) {
            logger.error(localFileName + "档案添加失败", e);
            return JSONResult.failure("档案添加失败");
        }
        return JSONResult.success(systemFiles);
    }

    /**
     * 删除上传的word文档并同时删除html文件:主要用于档案管理模块
     */
    @RequestMapping("deleteWordForDoc/{fileNo}")
    @ResponseBody
    public JSONResult deleteWordForDoc(@PathVariable String fileNo){
        try {
            systemFileService.deleteFileWordAndHtml(fileNo);
        } catch (FileNotFoundException e) {
            logger.error("删除文件不存在",e);
            return JSONResult.failure("该文件此前已被非法删除");
        }
        return JSONResult.success(fileNo);
    }

    /**
     * 删除单个文件
     *
     * @param fileno   文件编号
     * @param fileType 必须和文件保存时的要求一样，是实体类的名称,如何传入的fileType为空，说明是在添加方法中
     * @param pojoId   实体类的id
     */
    @RequestMapping(value = "deletefile/{fileno}", method = RequestMethod.POST)
    @ResponseBody
    public JSONResult deleteFile(HttpServletRequest request, @PathVariable String fileno, String fileType, Integer pojoId) {
        try {
            SystemFiles systemFiles = commonService.get(SystemFiles.class, fileno);
            if (fileType != null && !fileType.trim().equals("")) {
                switch (fileType.trim()) {
                    case "Task":
                        Task task = commonService.get(Task.class, pojoId);
                        String newFiles = task.getFiles().replace("," + fileno, "");
                        task.setFiles(newFiles);
                        commonService.updateEntity(task);
                        break;
                    default:
                        logger.error("该实体类不存在，请确认参数fileType");
                }
            }
            new File(systemFiles.getLocalPath() + File.separator + systemFiles.getName()).delete();//删除本地保存的此文件
            commonService.deleteEntityById(SystemFiles.class, fileno);
            logger.info(getUserInSession(request).getName() + "删除fileType文件：" + systemFiles.getName());
        } catch (Exception e) {
            logger.error("文件删除失败", e);
            return JSONResult.failure("该文件在系统保存中出现错误，不可删除");
        }
        return JSONResult.success(fileno);
    }

    /**
     * 下载本地文件
     */
    @RequestMapping("download/{fileNo}")
    public ResponseEntity<byte[]> download(@PathVariable String fileNo) throws IOException {
        SystemFiles systemFiles = commonService.get(SystemFiles.class, fileNo);
        String path = systemFiles.getLocalPath() + File.separator + systemFiles.getName();
        File file = new File(path);
        HttpHeaders headers = new HttpHeaders();
        String fileName = new String(systemFiles.getName().getBytes("UTF-8"), "iso-8859-1");//为了解决中文名称乱码问题
        headers.setContentDispositionFormData("attachment", fileName);
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file),
                headers, HttpStatus.CREATED);
    }

    /**
     * 下载本地文件
     */
    @RequestMapping("word/download/{fileNo}")
    public ResponseEntity<byte[]> uditorWordDownload(@PathVariable String fileNo) throws IOException {
        SystemFiles systemFiles = commonService.get(SystemFiles.class, fileNo);
        String path = systemFiles.getLocalPath() + File.separator + systemFiles.getNo() + "." + systemFiles.getSuffix();
        File file = new File(path);
        HttpHeaders headers = new HttpHeaders();
        String fileName = new String((systemFiles.getName() + "." + systemFiles.getSuffix()).getBytes("UTF-8"), "iso-8859-1");//为了解决中文名称乱码问题
        headers.setContentDispositionFormData("attachment", fileName);
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file),
                headers, HttpStatus.CREATED);
    }

    /**
     * 图片文件预览操作
     *
     * @param fileNo 文件no
     */
    @RequestMapping("showpic/{fileNo}")
    public String showPic(@PathVariable String fileNo, ModelMap modelMap) {
        SystemFiles systemFiles = commonService.get(SystemFiles.class, fileNo);
        modelMap.put("path", systemFiles.getPath() + File.separator + systemFiles.getName());
        System.out.println(fileNo);
        return "showpic";
    }

    /**
     * word转换为html文件格式后预览
     *
     * @param fileNo 文件编号
     */
    @RequestMapping("wordshow/{fileNo}")
    public String wordShow(@PathVariable String fileNo, ModelMap modelMap) {
        SystemFiles systemFiles = commonService.get(SystemFiles.class, fileNo);
        if (systemFiles == null) {
            modelMap.put("error", "该文件已被非法删除");
        }
        try {
            StringBuffer sb = FileUtil.readToBuffer(systemFiles.getLocalPath() + File.separator + systemFiles.getNo() + "." + "html", "gb2312");
            String contect = sb.toString();
            contect = contect.replaceAll("src=\"", "  src=\"/uploadpath/uploadify/" + systemFiles.getPath() + "/");//重置图片路径
            //System.out.println(contect);
            modelMap.put("content", contect);
        } catch (Exception e) {
            logger.error("该文件不存在");
        }
        return "wordshow";
    }

    /**
     * easypoi导出内容列表为Excel表格
     */
    @RequestMapping(value = "export", method = RequestMethod.POST)
    public void export(HttpServletRequest request, HttpServletResponse response) {
        response.setContentType(Constants.TEXT_CONTENT_TYPE);
        response.setCharacterEncoding(Constants.TEXT_CONTENT_TYPE);
        OutputStream out;
        try {
            out = response.getOutputStream();
            String query = request.getParameter(Constants.EXPORT_FORM_SUMIT_FIELD);
            System.out.println(query);
            if (StringUtil.isEmpty(query)) {
                out.write("未包含查询实体".getBytes(Constants.UTF_8));
                out.flush();
                out.close();
                return;
            }
            FormQuery formQuery = JSONObject.parseObject(URLDecoder.decode(query, Constants.UTF_8), FormQuery.class);
            if (formQuery == null) {
                out.write("错误的查询实体".getBytes(Constants.UTF_8));
                out.flush();
                out.close();
                return;
            }
            String entity = formQuery.getEntity();
            if (StringUtil.isEmpty(entity)) {
                out.write("实体名不能为空".getBytes(Constants.UTF_8));
                out.flush();
                out.close();
                return;
            }
            Class<?> entityClazz = Class.forName(Constants.BASE_ENTITY_PACKAGE + entity);
            if (entityClazz == null) {
                out.write("错误的实体名，无法转换".getBytes(Constants.UTF_8));
                out.flush();
                out.close();
                return;
            }

            String fileName = Optional.ofNullable(formQuery.getFileName()).orElse("导出信息表");
            String title = Optional.ofNullable(formQuery.getTitle()).orElse("导出信息表");
            // todo: 设置样式
            ExportParams ep = new ExportParams(title, "");
            //ep.setAddIndex(true);
            //ep.setIndexName("序号");
            //ep.setCreateHeadRows(true);
            //ep.setTitleHeight((short) 20);

            Page page = commonService.getPage(formQuery, entityClazz, false);
            Workbook workbook = ExcelExportUtil.exportExcel(ep, entityClazz, page.getRows());
            String encodedFileName = new String(fileName.getBytes(Constants.UTF_8), Constants.ISO_8859_1);
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            response.setHeader("Content-disposition", "attachment;filename=" + encodedFileName + ".xls");
            workbook.write(out);
            out.flush();
            out.close();

        } catch (IOException e) {
            logger.error("获取输出流失败：" + e.getMessage());
            e.printStackTrace();
        } catch (ClassNotFoundException notFoundException) {
            logger.error("实体转换异常[class: entity] " + notFoundException.getMessage());
        }
    }

}
